/**
 * 类类型 + 继承接口 + 混合类型 + 接口继承类
 * implements: extends 是继承父类，只要那个类不是声明final或者定义为abstract就能继承,JAVA中不支持多重继承，继承只能继承一个类，但implements可以实现多个接口，用逗号分开就行了。
 * */
/*接口继承类*/
class Control {
    private state:any
}
interface SelectabelControl extends Control {
    select();
}
class Button extends Control implements SelectabelControl {  //继承了Control,才能实现SelectabelControl接口
    select() {
    }
}
class TextBox extends Control {
    select(){}
}
class ImageC implements SelectabelControl {   //缺少私有成员state = 不行
    select() {
    }
}












/*混合类型*/
interface Counter {
    (start:number): string,
    interval: number,
    reset():void
}
function getCounter():Counter {
    let counter = (function(start:number){}) as Counter;
    counter.interval = 10;
    counter.reset = function(){};
    return counter
}
let c = getCounter();
c(10);









/*多接口继承*/
interface Shape {
    color: string
}
interface PenStroke {
    penWidth: number
}
interface Square extends Shape,PenStroke {
    sideLength: number
}
let square = {} as Square;
square.color = 'yellow';
square.penWidth = 10;
square.sideLength = 30;










/*新建工厂方法使用构造器*/
interface ClockInterface1 {
    tick()
}
interface ClockContructor1 {
    new(hour:number,minute:number):ClockInterface1
}
//工厂方法
function createClock(ctro:ClockContructor1,hour:number,minute:number):ClockInterface1{
    return new ctro(hour,minute);
}
class DigitalClock implements ClockInterface1 {
    constructor(h:number,m:number){}
    tick() {
        console.log('beep beep');
    }
}
class AnalogClock implements ClockInterface1 {
    constructor(h:number,m:number){}
    tick() {
        console.log('tick toc')
    }
}
let digital = createClock(DigitalClock,12,13);
let analog = createClock(AnalogClock,14,15);
console.log(digital);

// -----------------------------------------------
interface ClockInterface {  //实例接口
    currentTime: Date,
    setTime(d:Date)
}
interface ClockConstructor {  //构造器接口
    new(hour:number,minute:number)  //构造器签名
}
class Clock implements ClockInterface {
    currentTime: Date;
    constructor(h:number,m:number){}
    setTime(d: Date) {
        this.currentTime = d;
    }
}























/**
 * 额外属性检查 + 函数类型 + 可索引的类型
 * */
/*可索引的类型*/
// (只读索引类型)
interface ReadonlyStringArray{
    readonly [index:number]:string
}
let myOnly:ReadonlyStringArray = ['hardy','小方块'];
// myOnly[2] = 'hhardyy';
// -----------------------------------------------------
class Animal {
    name: string
}
class Dog extends Animal {
    bread: string
}
interface NotQkay {
    [x:number]:Dog,
    [x:string]:Animal
}
// ------------------------------------------------
interface StringArray {
    [index:number]:string
}
let myArray:StringArray = ['hardy','小方块'];
let mystr:string = myArray[0];

/*函数属性*/
interface SearchFunc {
    (source:string,subString:string):boolean
}
/* function(source:string,subString:string)
* 中的source和subString名字可以和接口的不一样，但是类型要一样，
* 只需要实现的规则和接口定义的规则一样就好了
* */
let mySearch:SearchFunc = function(source:string,subString:string):boolean{
    let result = source.search(subString);
    return result>-1;
};
console.log(mySearch('https:hhardyy.com','hhardyy'));
















/**
 * 可选属性 + 只读属性
 * ? = 可选，可有可没有
 * readonly = 只读
 * */
/*数组只读*/
let arr:ReadonlyArray<number> = [2,3,4,5];
/*变量只读*/
interface Point {
    readonly x:number,
    readonly y:number
}
let pont:Point = {x:1,y:2};


interface Square {
    color:string,
    area:number
}
interface SquareConfig {
    color?:string,
    width?:number,
    [propName:string]:any    //索引签名   表示可以允许有其他的字面量
}
function createCricle(config:SquareConfig):Square {
    let newSquare = { color:'red',area:100};
    newSquare.color = config.color?config.color:newSquare.color;
    newSquare.area =config.width?config.width*config.width:newSquare.area;
    return newSquare;
}
let mySquare = { color:'green',width: 200};
let newSquare = createCricle(mySquare);












/**
 * 普通接口定义
 * */
interface labelledValue {
    label:string
}
function printLabel(labelledObj:labelledValue){
    console.log(labelledObj.label);
}
let myObj = { size:10,label:'Size 10 Object' }
printLabel(myObj);